<script setup lang="ts">
import {ref, watch} from 'vue'
import {NInput, NRadioGroup, NRadio, NSpace, NSwitch, NInputNumber, NFormItem} from 'naive-ui'
import {useTable} from '@/composables/useTable'
import {fetchDeleteById, fetchMenuListPage, fetchSaveMenu, fetchUpdateMenu} from "@/api/menu"
import {
  ClickType,
  DEFAULT_MENU_MODEL,
  useFormRules,
  useColumns,
  useContextMenuOptions
} from '@/views/manager/menu/mock/useMenuConfig'
import SearchForm from './components/SearchForm.vue'
import BaseCrudPage from '@/components/page/BaseCrudPage.vue'
import BaseFormModal from '@/components/modal/BaseFormModal.vue'

defineOptions({name: 'Menu'})

// 状态管理
const optionType = ref<ClickType>(ClickType.NONE)
const showModal = ref(false)
const formValue = ref<Menu.MenuModel>({...DEFAULT_MENU_MODEL})

// 搜索参数
const searchParams = ref({
  name: '',
  title: '',
  menuType: null
})

// 表格配置
const {
  dataRef,
  loading,
  pagination,
  tableConfig,
  handlePageChange,
  refresh,
  rowKey,
  reset
} = useTable<Menu.MenuModel>({
  pageSize: 10,
  api: (params) => fetchMenuListPage({...params, ...searchParams.value}),
  immediate: true,
  minHeight: 560,
  maxHeight: 560,
  rowKey: (row: any) => row.id
})

// 处理点击事件
function handlerClick(type: ClickType, row: Menu.MenuModel) {
  optionType.value = type
  if (type === ClickType.UPDATE) {
    formValue.value = {...row}
    showModal.value = true
  } else if (type === ClickType.ADD) {
    formValue.value = {...DEFAULT_MENU_MODEL}
    showModal.value = true
  } else if (type === ClickType.ADD_DOWN) {
    formValue.value = {...DEFAULT_MENU_MODEL, id: row.id}
    showModal.value = true
  } else if (type === ClickType.DELETE) {
    if (row.id != null) {
      fetchDeleteById(row.id).then(() => refresh())
    }
  }
}

const columns = useColumns(handlerClick)
const contextMenuOptions = useContextMenuOptions(handlerClick)
const rules = useFormRules()

// 处理表单提交
async function handleSubmit(model: Menu.MenuModel) {
  try {
    if (optionType.value === ClickType.UPDATE) {
      await fetchUpdateMenu({
        ...model,
        path: model.route?.path ?? '',
        component: model.route?.component ?? ''
      })
    } else {
      await fetchSaveMenu({
        ...model,
        path: model.route?.path ?? '',
        component: model.route?.component ?? '',
        ...(optionType.value === ClickType.ADD_DOWN ? {parentId: model.id, id: null} : {})
      })
    }
    showModal.value = false
    formValue.value = {...DEFAULT_MENU_MODEL}
    refresh()
  } catch (error) {
    window.$message?.error('操作失败：' + error)
  }
}

// 监听 menuType 的变化
watch(() => formValue.value.menuType, (newMenuType) => {
  if (newMenuType === 2 || newMenuType == 1) {
    if (!formValue.value.route) {
      formValue.value.route = {
        path: '',
        component: ''
      }
    }
  }
})
</script>

<template>
  <BaseCrudPage
    :loading="loading"
    :data="dataRef"
    :columns="columns"
    :pagination="pagination"
    :table-config="tableConfig"
    :context-menu-options="contextMenuOptions"
    :row-key="rowKey"
    @update:page="handlePageChange"
  >
    <template #search>
      <SearchForm
        :on-search="refresh"
        :on-reset="reset"
      />
    </template>

    <template #modal>
      <BaseFormModal
        v-model:show="showModal"
        :title="optionType === ClickType.UPDATE ? '修改' : '添加'"
        :model="formValue"
        :rules="rules"
        @submit="handleSubmit"
      >
        <n-form-item label="菜单标题" path="title">
          <n-input v-model:value="formValue.title" placeholder="请输入菜单标题"/>
        </n-form-item>
        <n-form-item label="菜单名称" path="name">
          <n-input v-model:value="formValue.name" placeholder="请输入菜单名称"/>
        </n-form-item>
        <n-form-item label="菜单类型" path="menuType">
          <n-radio-group v-model:value="formValue.menuType" name="menuType">
            <n-space>
              <n-radio :value="1">菜单</n-radio>
              <n-radio :value="2">路由</n-radio>
              <n-radio :value="3">超链接</n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item>

        <template v-if="formValue.menuType === 1">
          <n-form-item label="菜单路径" path="route.path" v-if="formValue.route">
            <n-input v-model:value="formValue.route.path" placeholder="请输入菜单路径"/>
          </n-form-item>
        </template>

        <template v-else-if="formValue.menuType === 2">
          <n-form-item label="路由路径" path="route.path" v-if="formValue.route">
            <n-input v-model:value="formValue.route.path" placeholder="请输入路由路径"/>
          </n-form-item>
          <n-form-item label="路由组件" path="route.component" v-if="formValue.route">
            <n-input v-model:value="formValue.route.component" placeholder="请输入路由组件"/>
          </n-form-item>
        </template>

        <template v-else-if="formValue.menuType === 3">
          <n-form-item label="链接地址" path="href">
            <n-input v-model:value="formValue.href" placeholder="请输入链接地址"/>
          </n-form-item>
        </template>

        <n-form-item label="排序" path="order">
          <n-input-number v-model:value="formValue.order" clearable/>
        </n-form-item>

        <n-form-item label="菜单图标" path="icon">
          <n-input v-model:value="formValue.icon" placeholder="请输入菜单图标"/>
        </n-form-item>

        <n-form-item label="是否需要权限" path="requiresAuth">
          <n-switch v-model:value="formValue.requiresAuth"/>
        </n-form-item>

        <n-form-item label="是否禁用" path="disabled">
          <n-switch v-model:value="formValue.disabled"/>
        </n-form-item>

        <n-form-item label="是否显示" path="show">
          <n-switch v-model:value="formValue.show"/>
        </n-form-item>
      </BaseFormModal>
    </template>
  </BaseCrudPage>
</template>

<style scoped>
.container {
  padding: 16px;
  background-color: #f5f7fa;
  min-height: 100%;
}

:deep(.n-data-table) {
  background-color: #fff;
  border-radius: 4px;
}

:deep(.n-card) {
  background-color: transparent;
  box-shadow: none;
}

:deep(.n-card-header) {
  padding: 0 0 16px 0;
}

:deep(.n-button:not(:last-child)) {
  margin-right: 12px;
}

:deep(.n-form-item-label) {
  font-weight: 500;
}
</style>
